package app.gui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.LinkedList;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

import app.Main;
import app.conn.WebDB;

public class MainFrame extends JFrame {	
	public static final String CNFFILE = "CONFIG.TXT";
	public static final String SETFILE = "SETTINGS.TXT";
	public static final String RECFILE = "RECORDS.TXT";

	private static MainFrame instance; // Instance of Main Frame

	public JLabel status = new JLabel("Uživatel nepřihlášen");

	private File sdRoot;
	public File recFile;
	public File setFile;
	public File cnfFile;

	private JButton settingsButton;
	private JButton configButton;
	private JButton recordsButton;
	
	private JLabel pathLabel = new JLabel("Cesta nebyla vybrána");

	private RemotePanel remotePanel;

	/**
	 * Get instance of Main Frame class
	 * 
	 * @return MainFrame class singleton instance
	 */
	public static MainFrame getInstance() {
		if(instance == null) {
			instance = new MainFrame();
		}
		return instance;
	}

	/**
	 * Class Constructor
	 */
	private MainFrame() {		
		super(Main.FRAME_TITLE);
		setSize(new Dimension(400, 500));

		JPanel panel = new JPanel(new GridBagLayout());

		GridBagConstraints cs = new GridBagConstraints();
		cs.fill = GridBagConstraints.BOTH;
		cs.insets = new Insets(5, 10, 5, 10);
		cs.weightx = 1;

		JPanel sdPanel = new JPanel(new GridBagLayout());
		sdPanel.setBorder(BorderFactory.createTitledBorder("SD Karta"));

		JButton butOpen = new JButton("<html><center>Otevřít<br>úložiště</center></html>");
		butOpen.addActionListener(new OpenSDListener());
		cs.gridx = 0;
		cs.gridy = 0;
		cs.gridwidth = 1;
		cs.gridheight = 3;
		sdPanel.add(butOpen, cs);

		cs.insets = new Insets(5, 40, 5, 10);
		settingsButton = new JButton("Nastavení jednotky");
		settingsButton.addActionListener(new SettingsButtonListener());
		cs.gridx = 1;
		cs.gridy = 0;
		cs.gridwidth = 1;
		cs.gridheight = 1;
		sdPanel.add(settingsButton, cs);
		settingsButton.setEnabled(false);

		configButton = new JButton("Řídící data jednotky");
		configButton.addActionListener(new ConfigButtonListener());
		cs.gridx = 1;
		cs.gridy = 1;
		cs.gridwidth = 1;
		cs.gridheight = 1;
		sdPanel.add(configButton, cs);
		configButton.setEnabled(false);

		recordsButton = new JButton("Zobrazit záznamy");
		recordsButton.addActionListener(new RecordsButtonListener());
		cs.gridx = 1;
		cs.gridy = 2;
		cs.gridwidth = 1;
		cs.gridheight = 1;
		sdPanel.add(recordsButton, cs);
		recordsButton.setEnabled(false);


		cs.gridx = 0;
		cs.gridy = 3;
		cs.gridwidth = GridBagConstraints.REMAINDER;
		cs.gridheight = 1;
		sdPanel.add(pathLabel, cs);


		//cs.fill = GridBagConstraints.BOTH;
		cs.insets = new Insets(10, 10, 10, 10);
		cs.weightx = 1;

		cs.gridx = 0;
		cs.gridy = 0;
		cs.gridwidth = 1;
		cs.gridheight = 1;
		panel.add(sdPanel, cs);


		JPanel listPanel = new JPanel(new GridLayout(1, 1));
		listPanel.setBorder(BorderFactory.createTitledBorder("Vzdálená správa"));

		setRemotePanel(new RemotePanel());
		listPanel.add(new JScrollPane(getRemotePanel()));
		cs.gridx = 0;
		cs.gridy = 1;
		cs.gridwidth = 1;
		cs.gridheight = 1;
		cs.weighty = 1;
		panel.add(listPanel, cs);

		add(panel, BorderLayout.CENTER);

		JPanel statusBar = new JPanel(new FlowLayout(FlowLayout.LEADING));
		statusBar.add(status);

		add(statusBar, BorderLayout.PAGE_END);

		if(Main.isLogged() && Main.appcnf.getName() != null) {
			try {
				if(!WebDB.check(Main.getToken(), Main.getUserName())) {
					Main.showInfo("Neplatné přihlášení, přihlašte se znovu");
					Main.setToken(null, Main.getUserName());
					Main.appcnf.setToken(null);
					Main.appcnf.save();
					enableRemotePanel(false);
				}
				else {
					status.setText("Uživatel: ".concat(Main.appcnf.getName()));
					enableRemotePanel(true);
					WebDB.setRequestConfig();
				}
			} catch (IOException e) {
				Main.showError("Chyba připojení", "Uživatel byl odhlášen");
				Main.setToken(null, Main.getUserName());
				Main.appcnf.setToken(null);
				Main.appcnf.save();
				enableRemotePanel(false);
			}
		}
		else {
			enableRemotePanel(false);
		}

		setJMenuBar(createMenuBar());
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLocationRelativeTo(null);
		setResizable(false);
		setVisible(true);
	}

	/**
	 * MainFrame remote access menu bar 
	 * 
	 * @return JMenuBar with remote access settings
	 */
	private JMenuBar createMenuBar() {
		JMenuBar bar = new JMenuBar();
		/*
		JMenu testMenu = new JMenu("Test");
		testMenu.setMnemonic(KeyEvent.VK_T);
		bar.add(testMenu);

		JMenuItem testItem = new JMenuItem("test");
		testItem.addActionListener(new TestListener());
		testMenu.add(testItem);
		 */

		bar.add(Box.createHorizontalGlue());

		JMenu remoteMenu = new JMenu("Vzdálený přístup");
		remoteMenu.setMnemonic(KeyEvent.VK_V);
		bar.add(remoteMenu);

		JMenuItem registerItem = new JMenuItem("Založit účet");
		registerItem.setMnemonic(KeyEvent.VK_Z);
		registerItem.addActionListener(new RegisterListener());
		remoteMenu.add(registerItem);

		JMenuItem loginItem = new JMenuItem("Přihlásit");
		loginItem.setMnemonic(KeyEvent.VK_P);
		loginItem.addActionListener(new LoginListener());
		remoteMenu.add(loginItem);

		JMenuItem logoutItem = new JMenuItem("Odhlásit");
		logoutItem.setMnemonic(KeyEvent.VK_O);
		logoutItem.addActionListener(new LogoutListener());
		remoteMenu.add(logoutItem);

		JMenuItem settingsItem = new JMenuItem("Nastavení");
		settingsItem.setMnemonic(KeyEvent.VK_N);
		settingsItem.addActionListener(new SetupListener());
		remoteMenu.add(settingsItem);

		return bar;
	}

	/**
	 * Change enabled status to Remote Panel and all components
	 * 
	 * @param enabled Enabled / Disabled flag
	 */
	public void enableRemotePanel(boolean enabled) {
		getRemotePanel().setEnabled(enabled);
		for(Component c : getRemotePanel().getComponents()) {
			c.setEnabled(enabled);
		}

		if(enabled)
			((RemotePanel) getRemotePanel()).refresh();
		else
			getRemotePanel().removeAll();
	}

	public RemotePanel getRemotePanel() {
		return remotePanel;
	}

	public void setRemotePanel(RemotePanel remotePanel) {
		this.remotePanel = remotePanel;
	}

	/**
	 * Panel with remote units list
	 * 
	 * 
	 * @author Lukas Vavra
	 *
	 */
	public class RemotePanel extends JPanel {
		private String[] unitList;

		/**
		 * Remote Panel constructor
		 */
		public RemotePanel() {
			super(new GridBagLayout());
		}

		/**
		 * Get unit list from server and update panel
		 */
		public void refresh() {
			try {
				unitList = WebDB.getUnitList();
				if(unitList == null)
					return;
			} catch (IOException e) {
				Main.showError("Chyba připojení", "Nelze získat seznam vzdálených jednotek");
				return;
			}

			removeAll();

			GridBagConstraints cs = new GridBagConstraints();
			cs.insets = new Insets(10, 20, 10, 20);
			cs.fill = GridBagConstraints.BOTH;
			cs.weighty = 0;

			JButton unitBut;
			JButton removeBut;
			for(int i = 1; i < unitList.length; i++) {
				unitBut = new JButton(Integer.toString(i).concat(". ")
						.concat(unitList[i].split(" ", 2)[1]));
				unitBut.setActionCommand(unitList[i].split(" ", 2)[0]);
				unitBut.addActionListener(new UnitButtonListener());
				cs.gridx = 0;
				cs.weightx = 1;
				cs.gridy = i;
				add(unitBut, cs);

				removeBut = new JButton("X");
				removeBut.setActionCommand(unitList[i].split(" ", 2)[0]);
				removeBut.addActionListener(new RemoveButtonListener());
				cs.gridx = 1;
				cs.weightx = 0;
				cs.gridy = i;
				add(removeBut, cs);
			}

			revalidate();
			repaint();
		}

		/**
		 * Unit Button listener
		 * 
		 * @author Lukas Vavra
		 *
		 */
		private class UnitButtonListener implements ActionListener {
			@Override
			public void actionPerformed(ActionEvent e) {
				ConfigModel model = new ConfigModel();
				model.setRemoteAccess(true);
				model.setUnitId(e.getActionCommand());
				try {
					model.parseData(WebDB.getConfig(model.getUnitId()));
				} catch (IOException e1) {
					Main.showError("Chyba připojení", "Nelze získat data nastavení");				
				}
				new ConfigFrame(model);
			}			
		}

		/**
		 * Remove unit Button listener
		 * 
		 * @author Lukas Vavra
		 *
		 */
		private class RemoveButtonListener implements ActionListener {
			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					if(!WebDB.removeUnit(e.getActionCommand()))  {
						Main.showError("Chyba připojení", "Nelze odebrat jednotku");
						return;
					}
				} catch (IOException ex) {
					Main.showError("Chyba připojení", "Nelze odebrat jednotku");
					return;
				}
				refresh();
			}
		}
	}

	/**
	 * Action Listener to open greenhouse file system from SD card
	 * 
	 * @author Lukas Vavra
	 *
	 */
	private class OpenSDListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			JFileChooser chooser = new JFileChooser(Main.appcnf.getLastpath());
			chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

			// open file chooser
			if(chooser.showOpenDialog(getInstance()) == JFileChooser.APPROVE_OPTION) { 
				if(chooser.getSelectedFile() != null)
					chooser.setCurrentDirectory(chooser.getSelectedFile());

				// set SD Root 
				sdRoot = chooser.getSelectedFile();

				// look for greenhouse files
				for(String f : sdRoot.list()) {
					System.out.println(f);
					if(f.equals(CNFFILE)) cnfFile = new File(sdRoot, CNFFILE);
					if(f.equals(RECFILE)) recFile = new File(sdRoot, RECFILE);
					if(f.equals(SETFILE)) setFile = new File(sdRoot, SETFILE);
				}

				// Setting file
				if(setFile == null) {
					setFile = new File(sdRoot, SETFILE);
					try {
						if(!setFile.createNewFile()) {
							Main.showError("Chyba souboru", "Nelze vytvořit soubor SETTINGS.TXT");
							return;
						}
						PrintWriter w = new PrintWriter(setFile);
						w.println("Nový skleník");
						w.println("0");
						w.close();

					} catch (IOException ex) {
						Main.showError("Chyba souboru", "Nelze vytvořit soubor SETTINGS.TXT");
						return;
					}
				}
				settingsButton.setEnabled(true);

				// Config file
				if(cnfFile == null) {
					cnfFile = new File(sdRoot, CNFFILE);
					try {
						if(!cnfFile.createNewFile()) {
							Main.showError("Chyba souboru", "Nelze vytvořit soubor CONFIG.TXT");
							return;
						}
					} catch (IOException ex) {
						Main.showError("Chyba souboru", "Nelze vytvořit soubor CONFIG.TXT");
						return;
					}
				}
				configButton.setEnabled(true);

				// Records file
				if(recFile != null) {
					recordsButton.setEnabled(true);
				}

				// save last selected path
				Main.appcnf.setLastpath(sdRoot.getPath());
				Main.appcnf.save();
				pathLabel.setText("Cesta: ".concat(sdRoot.getPath()));
			}
		}
	}

	/**
	 * Settings Button listener
	 * - open SettingsDialog
	 * - read and save SETTINGS.TXT
	 * 
	 * @author Lukas Vavra
	 *
	 */
	private class SettingsButtonListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent arg0) {
			if(setFile != null && !setFile.canRead()) {
				Main.showError("Chyba souboru", "Nelze načíst soubor ".concat(SETFILE));
				return;
			}	

			new SettingsDialog(MainFrame.getInstance());
		}

	}

	/**
	 * Config Button listener
	 * - open GreenhouseFrame
	 * - read and save CONFIG.TXT
	 * 
	 * @author Lukas Vavra
	 *
	 */
	private class ConfigButtonListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent arg0) {
			LinkedList<String> config = new LinkedList<String>();
			try {
				BufferedReader reader = new BufferedReader(new FileReader(cnfFile));
				String line;
				while ((line = reader.readLine()) != null) {
					config.add(line);
				}
				reader.close();
			} catch (IOException e) {
				Main.showError("Chyba souboru", "Nelze otevřít soubor CONFIG.TXT");	
				return;
			}
			if(config.size() > 0) {
				ConfigModel model = new ConfigModel(config.toArray(new String[config.size()]));
				model.setRemoteAccess(false);
				new ConfigFrame(model);
			}
			else {
				new ConfigFrame();
			}
		}

	}


	/**
	 * Records Button listener
	 * -read RECORDS.TXT
	 * - open RecordsDialog 
	 * 
	 * @author Lukas Vavra
	 *
	 */
	private class RecordsButtonListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent arg0) {
			if(recFile != null && !recFile.canRead()) {
				Main.showError("Chyba souboru", "Nelze načíst soubor ".concat(RECFILE));
				return;
			}	
			RecordsModel model = new RecordsModel();
			model.setRemoteAccess(false);
			new RecordsDialog(model);
		}
	}

	/**
	 * Register menu item listener
	 * 
	 * @author Lukas Vavra
	 *
	 */
	private class RegisterListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent arg0) {
			new RegisterDialog(getInstance());
		}

	}

	/**
	 * Login menu item listener
	 * 
	 * @author Lukas Vavra
	 *
	 */
	private class LoginListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent arg0) {
			new LoginDialog(getInstance());
		}
	}

	/**
	 * Logout menu item listener
	 * 
	 * @author Lukas Vavra
	 *
	 */
	private class LogoutListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent arg0) {
			if(Main.isLogged()) {
				Main.setToken(null, null);
				Main.appcnf.setSavelogin(false);
				Main.appcnf.setName(null);
				Main.appcnf.setToken(null);
				Main.appcnf.save();

			}
			status.setText("Uživatel nepřihlášen");
			enableRemotePanel(false);
		}
	}

	/**
	 * Settings menu item listener
	 * 
	 * 
	 * @author Lukas Vavra
	 *
	 */
	private class SetupListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			new SetupDialog(MainFrame.getInstance());
		}
	}

	/**
	 * Only for testing
	 * 
	 * @author Lukas Vavra
	 *
	 */
	private class TestListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent arg0) {
		}

	}
}
